/*
 * flash.c
 *
 * Created: 7/11/2013 12:02:36 PM
 *  Author: Tim
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>

#include "../board/board.h"
#include "flash.h"
#include "../features/allocations.h"

flash_t flash;

void	spiInit()
{
	prEnable(SPIC_PR);
	SPIC.CTRL = SPI_CLK2X_bm			|
				SPI_ENABLE_bm			|
				SPI_MASTER_bm			|
				SPI_MODE_3_gc			|
				SPI_PRESCALER_DIV4_gc	;
}

void chipErase()
{
	//wait for the chip to finish what its doing
	while(readStatusReg() & STSRG_BUSY_msk);
	//must do this prior to chip erase
	writeEnable();	
	//now perform chip erase
	flashSel();
	spiWrite(chipErase_cmd);
	flashDeSel();
}

//this function returns a 128 word array of a given adc channel flash data
uint32_t flashGetData(uint32_t address, uint8_t channel,uint16_t *channelData)
{	
	
	//channel is not the same as the adc channel
	//if adc channel 3 was the only channel enabled it would be referenced as 0 here
	//numbering is from the lowest enabled ADC Channel to the highest 0-3 max
	
    uint16_t genReadBuffer[128];
	uint32_t startAddress = address;
	uint16_t i;
	
	for(;address<(startAddress + 128*flash.addrInc);)
	{
		//read page	
		readPage(&genReadBuffer,address);
			
		//parse data			
		for(i=0;i<128;i+=flash.numChannels)
		{
			//grab only the data that pertains to the correct channel
				//channels is the static offset used to select the right "channel" data
				//i*numChannels provides the dynamic offset
			
			//if data is outside of the sample memory range set this data to 0 	
			if((i + channel) > flash.finAddr)	*channelData++ = 0;
			//otherwise populate the data
			else								*channelData++ = genReadBuffer[i + channel];
			
			//increment the baseAddress appropriately
			address += flash.addrInc;
			//**Note**
			//when 3 channels are active this will ensure data is not lost when reading new pages
			//by keeping track of the current address we will start our next page read at the appropriate location
			// 128/3 = 42 with a remainder of 2 samples
			// the second page should be offset 126 from the first in order to get all the data 
		}
	}
	return address;		
}

void readPage(uint16_t *buffer, uint32_t address)
{
	
	uint16_t i,temp;
	
	//enable the device
		flashSel();

		//send command
		spiWrite(readData_cmd);
	
		//send address to start from
		spiWrite((0xFF0000 & address)>>16);
		spiWrite((0x00FF00 & address)>>8);
		spiWrite(0x0000FF & address);
	
		//store page to buffer
		for(i=0;i<128;i++)
		{
			temp = (spiRead())<<8;
			temp |= spiRead();
			*buffer++ = temp;
		}
	//finish opp and deselect the device
		flashDeSel();
}

